﻿using System;
using System.ComponentModel.Composition;
using System.IO;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.Win32;
using Red.Scripts.Defines;
using Red.Scripts.Options.Tool.Bar.Extensions;

namespace Red.Scripts.Options.Tool.Bar
{
    [Export]
    public class BuildAndContinue
    {
        #region Imports

        public DTE DTE { get; private set; }

        [Import( "Build" )]
        public ILogPane LogPane { get; private set; }

        #endregion Imports

        #region C-Tor

        [ImportingConstructor]
        public BuildAndContinue( SVsServiceProvider ServiceProvider )
        {
            DTE = (DTE)ServiceProvider.GetService( typeof( DTE ) );
        }

        #endregion C-Tor

        #region Public Methods

        public void Initialize( OleMenuCommandService commandService )
        {
            commandService.InitializeButton( Toolbar.Guid, Toolbar.BuildAndContinueButtonId, DoBuild );
        }

        #endregion Public Methods

        #region Private Methods

        private void DoBuild( object sender, EventArgs e )
        {
            RegistryKey key = Registry.LocalMachine.OpenSubKey( @"SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" );
            string msbuildPath = key?.GetValue( "MSBuildToolsPath" ) as string;

            if ( string.IsNullOrEmpty( msbuildPath ) )
                return;

            string solutionPath = DTE.Solution?.FullName;

            if ( string.IsNullOrEmpty( solutionPath ) )
                return;

            DTE.Documents?.SaveAll();

            string configuration = DTE.Solution.SolutionBuild.ActiveConfiguration.Name;

            System.Diagnostics.Process process = new System.Diagnostics.Process();

            process.StartInfo.FileName = Path.Combine( msbuildPath, "msbuild.exe" );
            process.StartInfo.Arguments = $"{solutionPath} /p:Configuration={configuration}";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.EnableRaisingEvents = true;

            process.OutputDataReceived += HandleOutput;
            process.ErrorDataReceived += HandleOutput;
            process.Exited += Process_Exited;

            process.Start();
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            LogPane?.Activate();
        }

        #endregion Private Methods

        #region Event Handlers

        private void Process_Exited( object sender, EventArgs e )
        {
            System.Diagnostics.Process process = (System.Diagnostics.Process)sender;

            process.OutputDataReceived -= HandleOutput;
            process.ErrorDataReceived -= HandleOutput;
            process.Exited -= Process_Exited;
        }

        void HandleOutput( object sender, System.Diagnostics.DataReceivedEventArgs e )
        {
            LogPane?.PrintLine( e.Data );
        }

        #endregion Event Handlers
    }
}
